﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace SpeedTest
{
	public partial class PanelBulkAssign : UserControl
	{
		private Data data = null;
		private string releaseID = String.Empty;
		private string planID = String.Empty;

		public PanelBulkAssign(Data data, string planID, string releaseID)
		{
			InitializeComponent();
			this.data = data;
			this.releaseID = releaseID;
			this.planID = planID;

			PopulatePlans(releaseID, planID);
			lstTester.ValueMember = "Value";
			lstTester.DisplayMember = "Text";

			if (data != null)
			{
				DataTable dt = data.GetUsers();
				FillList(dt, dt.Columns["ID"].Ordinal, dt.Columns["UserName"].Ordinal, lstTester);
			}
		}

		//TODO: Move to class - used throughout
		private void FillList(DataTable table, int valueIndex, int textIndex, ListBox list)
		{
			if (table != null && table.Rows.Count > 0)
			{
				list.Items.Clear();

				for (int i = 0; i < table.Rows.Count; i++)
				{
					ComboItem ci = new ComboItem();
					ci.Text = table.Rows[i][textIndex].ToString();
					ci.Value = table.Rows[i][valueIndex].ToString();

					list.Items.Add(ci);
				}
			}
		}

		private void PopulatePlans(string releaseID, string planID)
		{
			if (data.State == ConnectionState.Connected)
			{
				DataTable dt = null;

				if (planID != String.Empty)
				{
					dt = data.GetPlanByID(planID);
				}
				else
				{
					dt = data.GetPlansByRelease(releaseID);
				}

				if (dt.Rows.Count > 0)
				{
					for (int i = 0; i < dt.Rows.Count; i++)
					{
						//add tree items
						TreeNode tn = new TreeNode(dt.Rows[i]["ReferenceNumber"].ToString() + " " + dt.Rows[i]["Description"].ToString());
						TreeItem ti = new TreeItem();
						ti.ID = dt.Rows[i]["ID"].ToString();
						ti.ItemType = NodeType.PlanNode;
						tn.Tag = ti;
						tn.ImageIndex = 0;
						tn.SelectedImageIndex = 0;
						treeNavigation.Nodes.Add(tn);

						PopulateCaseSuites(ti.ID);
						tn.ExpandAll();
					}
				}
				else
				{
					return;
				}
			}
		}

		private void PopulateCaseSuites(string planID)
		{
			if (data.State == ConnectionState.Connected)
			{
				Filter filter = new Filter();
				filter.Plan = planID;

				DataTable dt = data.GetCaseSuitesByFilter(filter);

				TreeNode currNode = null;

				if (dt.Rows.Count > 0)
				{
					for (int i = 0; i < dt.Rows.Count; i++)
					{
						//add tree items
						TreeNode tn = null;
						TreeItem ti = new TreeItem();
						ti.ID = dt.Rows[i]["ID"].ToString();
						ti.ItemType = (NodeType)Int32.Parse(dt.Rows[i]["NodeType"].ToString());

						if (ti.ItemType == NodeType.CaseNode)
						{
							 tn = new TreeNode(dt.Rows[i]["Description"].ToString() + GetTesterAssignment(ti.ID));
						}
						else { tn = new TreeNode(dt.Rows[i]["Description"].ToString()); }

						ti.Path = dt.Rows[i]["Path"].ToString();
						tn.Tag = ti;

						if (ti.ItemType == NodeType.CaseNode)
						{
							tn.ImageIndex = 2;
							tn.SelectedImageIndex = 2;
						}
						else
						{
							tn.ImageIndex = 1;
							tn.SelectedImageIndex = 1;
						}

						TreeNode parentNode = FindParent(dt.Rows[i]["ParentPlanID"].ToString(), dt.Rows[i]["Path"].ToString(), currNode);
						if (parentNode != null) { parentNode.Nodes.Add(tn); }

						currNode = tn;
					}

				}
				else
				{
					return;
				}
			}

		}

		public TreeNode FindParent(string parentID, string path, TreeNode currNode)
		{
			if (currNode == null || path.Length == 3) { return FindPlanParent(parentID); }
			else
			{
				TreeItem ti = (TreeItem)currNode.Tag;

				if (path.Length > ti.Path.Length)
				{
					//it's a child of the currNode
					return currNode;
				}

				if (path.Length == ti.Path.Length)
				{
					//it's a sibling of the currChild
					return currNode.Parent;
				}

				if (path.Length < ti.Path.Length)
				{
					//move up
					return FindParent(parentID, path, currNode.Parent);
				}
			}

			return null;
		}

		private TreeNode FindPlanParent(string parentID)
		{
			for (int i = 0; i < treeNavigation.Nodes.Count; i++)
			{
				TreeNode node = treeNavigation.Nodes[i];
				TreeItem ti = (TreeItem)node.Tag;

				if (ti.ID == parentID)
				{
					return node;
				}
			}

			return null; //not found
		}

		private void treeNavigation_AfterCheck(object sender, TreeViewEventArgs e)
		{
			//check node type
			//if it's a plan or a suite, check/ uncheck child items
			TreeItem ti = (TreeItem)e.Node.Tag;
			if (ti != null)
			{
				switch (ti.ItemType)
				{
					case NodeType.PlanNode:
						CheckChildren(e.Node, e.Node.Checked);
						break;
					case NodeType.SuiteNode:
						CheckChildren(e.Node, e.Node.Checked);
						break;
					case NodeType.CaseNode:
						break;
				}
			}
		}

		private void CheckChildren(TreeNode parentNode, bool isChecked)
		{
			if (parentNode != null && parentNode.Nodes.Count > 0)
			{
				foreach (TreeNode node in parentNode.Nodes)
				{
					node.Checked = isChecked;
					if (node.Nodes.Count > 0)
					{
						CheckChildren(node, isChecked);
					}
				}
			}
		}

		private void BulkAssign()
		{
			foreach (TreeNode node in treeNavigation.Nodes)
			{
				BulkAssignChildren(node);
			}
		}

		private void BulkAssignChildren(TreeNode parentNode)
		{
			if (parentNode != null & parentNode.Nodes.Count > 0)
			{
				foreach (TreeNode node in parentNode.Nodes)
				{
					TreeItem ti = (TreeItem)node.Tag;
					if (ti != null && ti.ItemType == NodeType.CaseNode && node.Checked)
					{
						UpdateTesterAssignments(ti.ID);
					}

					if (node.Nodes.Count > 0)
					{
						BulkAssignChildren(node);
					}
				}
			}
		}

		private void UpdateTesterAssignments(string itemID)
		{
			//Delete all first
			if (data.DeleteTesterAssignmentByCaseID(itemID))
			{
				//Add back in the current assignment
				for (int i = 0; i < lstTester.CheckedItems.Count; i++)
				{
					ComboItem ci = (ComboItem)lstTester.CheckedItems[i];

					DataTable table = new DataTable();
					table.Columns.Add("CaseID");
					table.Columns.Add("TesterID");

					string[] row = new string[2];
					row[0] = itemID;
					row[1] = ci.Value;

					table.Rows.Add(row);

					data.InsertTesterAssignment(table);
				}
			}
			else
			{
				MessageBox.Show("An error occurred while trying to update the assigned testers");
			}
		}

		private string GetTesterAssignment(string itemID)
		{
			DataTable testerAsgnTable = null;
			string assignedTesters = "  [";

			if (data != null) { testerAsgnTable = data.GetTesterAssignmentsByCaseID(itemID); }

			if (testerAsgnTable != null && testerAsgnTable.Rows.Count > 0)
			{
				for (int i = 0; i < testerAsgnTable.Rows.Count; i++)
				{
					assignedTesters += testerAsgnTable.Rows[i]["Name"].ToString();
					if (i != testerAsgnTable.Rows.Count - 1)
					{
						assignedTesters += ", ";
					}
				}
			}
			else { return String.Empty; }	//we don't want the brackets if there are no assigned testers.

			assignedTesters += "]";

			return assignedTesters;
		}

		private void chkSelectAll_CheckedChanged(object sender, EventArgs e)
		{
			treeNavigation.Enabled = !chkSelectAll.Checked;

			foreach (TreeNode node in treeNavigation.Nodes)
			{
				node.Checked = chkSelectAll.Checked;
				CheckChildren(node, chkSelectAll.Checked);
			}
		}

		private void btnSave_Click(object sender, EventArgs e)
		{
			if (lstTester.CheckedItems.Count > 0)
			{
				BulkAssign();
				treeNavigation.Nodes.Clear();
				PopulatePlans(releaseID, planID);
				MessageBox.Show("Bulk Assignment Complete");
			}
			else
			{
				MessageBox.Show("You must select at least one tester");
			}
		}
	}
}
